package com.cskaoyan.javase.oop2.encapsulate._1extends._10final._3variable._2member;
/**
 * final修饰成员变量表示该成员变量变成了一个常量，它的取值不可变,除此之外它在内存中的位置，生命周期，使用方式等都不会改变。
 *
 * 语法：
 * [访问权限修饰符] final 数据类型 变量名;
 *
 * 成员常量和成员变量还是有区别的,由于常量它的取值不可改变,所以常量只能进行唯一的一次赋值
 * 那么这时如果默认初始化还生效的话,那它就会占用一次赋值机会,这样就没法后续赋值了
 * 常量的赋值,必须进行一次,也只能进行一次.
 * 所以成员常量的赋值,在new对象过程中,必须依赖于以下方式:
 *      1.显式赋值
 *      2.构造器赋值
 *      3.构造代码块赋值
 * 以上三种赋值方式,必须选择其一,也只能选择其一.
 *
 * 注意事项:
 *      1.如果选择用构造器给成员常量赋值,那么需要注意类中的每一个构造器都需要能够给成员常量赋值,少一个都不行.
 *
 *      2.(重点)
 *      final修饰的成员变量,一个成员常量,它是不是一个真正意义上的常量?
 *      真正意义上的常量: G,PI等
 *      显然不是,创建不同的对象,成员常量的取值是可以不同的,所以它不是一个真正意义上的常量
 *      在java中如果希望定义真正意义上的常量
 *      首先就需要保证这个变量在整个类的全局是独一份的
 *      它就是final修饰的静态成员变量
 *
 * @since 09:59
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*int num;
        // Variable 'num' might not have been initialized
        System.out.println(num);*/

        Student s = new Student(1);
        System.out.println(s.name);
        System.out.println(s.age);
        System.out.println(s.id);

        // s.id = 2;

        Student s2 = new Student(10);
        System.out.println(s2.id);
    }
}
class Student{
    // Variable 'age' might not have been initialized
    // final int age;
    final int age = 18;
    final String name;
    {
        name = "张三";
    }
    final int id;

    public Student(int id) {
        this.id = id;
    }

    public Student() {
        id = 100;
    }
}